package jp.gr.java_conf.genzo.wifinotify;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import jp.gr.java_conf.genzo.wifinotify.util.LogUtil;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

import com.google.ads.AdRequest;
import com.google.ads.AdView;

/**
 * メインActivity
 */
public class WifiNotifyActivity extends Activity {

	@SuppressWarnings("unused")
	private static final String TAG = WifiNotifyActivity.class.getSimpleName();
	private MenuArrayAdapter mAdapter = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

		setContentView(R.layout.main);
		// Look up the AdView as a resource and load a request.
		AdView adView = (AdView) this.findViewById(R.id.adView);
		AdRequest req = new AdRequest();
		// req.addTestDevice(AdRequest.TEST_EMULATOR);
		adView.loadAd(req);

		ListItem[] itemList = new ListItem[] {
				new ListItem(MODE_TITLE, R.string.main_text_wifi_ope, -1, null),
				new ListItem(MODE_WIFI, R.string.main_text_wifi, -1, null),
				new ListItem(MODE_WIFI_AP, R.string.main_text_tethering, -1,
						null),
				new ListItem(MODE_TITLE, R.string.main_text_wifi_log, -1, null),
				new ListItem(MODE_NEXT_PAGE, R.string.main_text_preferences,
						R.drawable.ic_menu_preferences,
						WifiNotifyPreferenceActivity.class),
				new ListItem(MODE_NEXT_PAGE,
						R.string.main_text_preferences_ssid,
						R.drawable.ic_menu_manage, ExcludeSSIDActivity.class),
				new ListItem(MODE_NEXT_PAGE, R.string.main_text_log,
						R.drawable.ic_menu_agenda, LogActivity.class),
				new ListItem(MODE_NEXT_PAGE, R.string.main_text_log_map,
						R.drawable.ic_menu_mapmode, LogMapActivity.class), };

		mAdapter = new MenuArrayAdapter(this, R.id.main_list, itemList);

		final ListView list = (ListView) findViewById(R.id.main_list);
		list.setAdapter(mAdapter);
		list.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> arg0, View arg1,
					int position, long arg3) {
				mAdapter.execute(position);
			}
		});

		Intent intent = getIntent();
		if (intent != null && intent.getExtras() != null) {
			Class<?> clazz = (Class<?>) intent.getExtras().get("NEXT_CLASS");
			startActivity(new Intent(this, clazz));
		}

	}

	class MenuArrayAdapter extends ArrayAdapter<ListItem> {

		public MenuArrayAdapter(Context context, int textViewResourceId,
				ListItem[] objects) {
			super(context, textViewResourceId, objects);
			mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		}

		LayoutInflater mInflater = null;;

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {

			ListItem item = getItem(position);

			if (convertView == null) {
				convertView = mInflater.inflate(R.layout.main_list, null);
			}

			if (item.mMode == MODE_TITLE) {
				convertView.findViewById(R.id.main_list_head).setVisibility(
						View.VISIBLE);
				convertView.findViewById(R.id.main_list_data).setVisibility(
						View.GONE);
				((TextView) convertView.findViewById(R.id.main_list_head_title))
						.setText(item.mResID);
			} else {

				convertView.findViewById(R.id.main_list_head).setVisibility(
						View.GONE);
				convertView.findViewById(R.id.main_list_data).setVisibility(
						View.VISIBLE);

				int visible = View.GONE;
				visible = item.mMode != MODE_NEXT_PAGE ? View.VISIBLE
						: View.GONE;
				ToggleButton btn = (ToggleButton) convertView
						.findViewById(R.id.main_list_toggle);
				btn.setVisibility(visible);
				btn.setTag(position);
				btn.setEnabled(item.mEnable);
				btn.setChecked(item.mOn);

				visible = item.mMode == MODE_NEXT_PAGE ? View.VISIBLE
						: View.GONE;
				ImageView iv = (ImageView) convertView
						.findViewById(R.id.main_list_image);
				iv.setVisibility(visible);
				if (visible == View.VISIBLE) {
					iv.setImageResource(item.mImageID);
				}

				((TextView) convertView.findViewById(R.id.main_list_title))
						.setText(item.mResID);
			}

			return convertView;
		}

		@Override
		public boolean isEnabled(int position) {
			ListItem item = getItem(position);
			return item.mEnable;
		}

		void refresh() {
			notifyDataSetChanged();
			notifyDataSetInvalidated();
		}

		void execute(int position) {
			ListItem item = getItem(position);
			if (item.mEnable == false) {
				return;
			}

			switch (item.mMode) {
			case MODE_NEXT_PAGE:
				startActivity(new Intent(WifiNotifyActivity.this, item.mNextCls));
				break;
			case MODE_WIFI:
				changeWifi(item);
				break;
			case MODE_WIFI_AP:
				changeWifiAp(item);
				break;
			}

			refresh();
		}

		public void changeWifi(ListItem item) {
			WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
			wifiApEnabled(wm, false);
			wm.setWifiEnabled(!wm.isWifiEnabled());
			item.mEnable = false;
			setProgressBarIndeterminateVisibility(true);
		}

		public void changeWifiAp(ListItem item) {
			WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
			wm.setWifiEnabled(false);
			wifiApEnabled(wm, !isWifiApEnabled(wm));
			item.mEnable = false;
			setProgressBarIndeterminateVisibility(true);
		}

		public void setWifiMode(boolean enable) {
			ListItem item = getItem(1);
			item.mOn = enable;
			item.mEnable = true;
			refresh();
			setProgressBarIndeterminateVisibility(false);
		}

		public void setWifiApMode(boolean enable) {
			ListItem item = getItem(2);
			item.mOn = enable;
			item.mEnable = true;
			refresh();
			setProgressBarIndeterminateVisibility(false);
		}
	}

	private static final int MODE_TITLE = -1;
	private static final int MODE_WIFI = 0;
	private static final int MODE_WIFI_AP = 1;
	private static final int MODE_NEXT_PAGE = 2;

	class ListItem {
		boolean mEnable = true;
		boolean mOn = false;
		int mMode = MODE_NEXT_PAGE;

		int mResID = -1;
		int mImageID = -1;

		Class<?> mNextCls = null;

		public ListItem(int mode, int resID, int imageID, Class<?> nextCls) {
			mMode = mode;
			mResID = resID;
			mImageID = imageID;
			mNextCls = nextCls;

			mEnable = mMode != MODE_TITLE;

		}
	}

	@Override
	protected void onStart() {
		super.onStart();
		IntentFilter filter = new IntentFilter();
		filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
		filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
		filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
		filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
		registerReceiver(mWifiApReceiver, filter);
		WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);

		mAdapter.setWifiMode(wm.isWifiEnabled());
		mAdapter.setWifiApMode(isWifiApEnabled(wm));

	}

	@Override
	protected void onResume() {
		super.onResume();
	}

	@Override
	protected void onStop() {
		super.onStop();
		unregisterReceiver(mWifiApReceiver);
	}

	private static final String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED";
	private static final int WIFI_AP_STATE_DISABLED = 1;
	private static final int WIFI_AP_STATE_DISABLED_4 = 10;
	private static final int WIFI_AP_STATE_ENABLED = 3;
	private static final int WIFI_AP_STATE_ENABLED_4 = 13;

	private BroadcastReceiver mWifiApReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {

			LogUtil.println("BroadcastReceiver#onReceive action="+ intent.getAction());

			if (WIFI_AP_STATE_CHANGED_ACTION.equals(intent.getAction())) {
				if (intent.getExtras() != null) {
					switch (intent.getExtras().getInt(
							WifiManager.EXTRA_WIFI_STATE, -1)) {
					case WIFI_AP_STATE_DISABLED:
					case WIFI_AP_STATE_DISABLED_4:
						mAdapter.setWifiApMode(false);
						break;
					case WIFI_AP_STATE_ENABLED:
					case WIFI_AP_STATE_ENABLED_4:
						mAdapter.setWifiApMode(true);
						break;
					default:
						break;
					}
				}
			} else if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent
					.getAction())) {
				if (intent.getExtras() != null) {
					switch (intent.getExtras().getInt(
							WifiManager.EXTRA_WIFI_STATE, -1)) {
					case WifiManager.WIFI_STATE_DISABLED:
						mAdapter.setWifiMode(false);
						break;
					case WifiManager.WIFI_STATE_ENABLED:
						mAdapter.setWifiMode(true);
						break;
					default:
						break;
					}
				}
			} else if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent
					.getAction())
					|| WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(intent
							.getAction())) {
				NetworkInfo ni = intent
						.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
				if (ni != null && ni.getType() == ConnectivityManager.TYPE_WIFI) {
					// WifiManager wm = (WifiManager)
					// getSystemService(WIFI_SERVICE);
					// ToggleButton btnWifi = (ToggleButton)
					// findViewById(R.id.btn_wifi);
					// btnWifi.setChecked(wm.isWifiEnabled());
				}
			}

		}
	};

	private boolean isWifiApEnabled(WifiManager wm) {
		try {
			Boolean result = (Boolean) invoke(wm, new Object[] {},
					"isWifiApEnabled", new Class[] {});
			return result.booleanValue();
		} catch (Throwable t) {
			throw new RuntimeException(t);
		}
	}

	private void wifiApEnabled(WifiManager wm, boolean enabled) {
		try {
			WifiConfiguration conf = (WifiConfiguration) invoke(wm,
					new Object[] {}, "getWifiApConfiguration", new Class[] {});
			invoke(wm, new Object[] { conf, enabled }, "setWifiApEnabled",
					new Class[] { WifiConfiguration.class, boolean.class });
		} catch (Throwable t) {
			throw new RuntimeException(t);
		}
	}

	private static Object invoke(Object obj, Object[] args, String name,
			Class<?>[] parameterTypes) throws Throwable {

		Object result = null;
		Class<?> cls = obj.getClass();

		do {
			try {
				Method method = cls.getDeclaredMethod(name, parameterTypes);
				method.setAccessible(true);

				result = method.invoke(obj, args);
				break;

			} catch (NoSuchMethodException e) {
				// 親クラスの型でリトライ
				cls = cls.getSuperclass();
			} catch (InvocationTargetException e) {
				throw e.getCause();
			} catch (Throwable e) {
				e.printStackTrace();
				break;
			}
		} while (cls != null);

		return result;
	}

	private long mPreBackKey = 0;
	Toast mToast = null;

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (mPreBackKey == 0
					|| System.currentTimeMillis() - mPreBackKey > 2000) {
				mPreBackKey = System.currentTimeMillis();
			}

			if (mToast != null){
				mToast.cancel();
				mToast = null;
			}

			if (System.currentTimeMillis() - mPreBackKey > 500) {
				return super.onKeyDown(keyCode, event);
			} else {
				mToast = Toast.makeText(this, R.string.main_toast_exit,
						Toast.LENGTH_SHORT);
				mToast.show();
				return true;
			}
		} else {
			return super.onKeyDown(keyCode, event);
		}
	}
}